#include "uid_session_map.h"
#include "base/logging.h"

namespace imserver {

void UidSessionMap::Add(int64_t uid, const std::string & session) {
  if (session.empty()) {
    LOG_WARN("UidSessionMap Add, uid=" << uid << " empty sesssion!");
    return;
  }
  uid_sessions_[uid].insert(session);
  LOG_INFO("UidSessionMap Add, uid=" << uid << " sesssion=" << session);

//MapType::const_iterator it = uid_sessions_.find(uid);

//if (it != uid_sessions_.end()) {
//  LOG_DEBUG("UidSessionMap Get, uid=" << uid << " session_size=" << it->second.size());
//} else {
//  LOG_DEBUG("UidSessionMap Get, uid=" << uid << " no session");
//}
}

int UidSessionMap::Remove(int64_t uid, const std::string & session) {
  LOG_INFO("UidSessionMap Remove, uid=" << uid << " sesssion=" << session);
  MapType::iterator mit = uid_sessions_.find(uid);

  if (mit != uid_sessions_.end()) {
    std::set<std::string>::iterator sit = mit->second.find(session);
    if (sit != mit->second.end()) {
      mit->second.erase(sit);
    }
    if (mit->second.empty()) {
      uid_sessions_.erase(mit);
    }
  }

  return 0;
}

const std::set<std::string> & UidSessionMap::Get(int64_t uid) const {
  MapType::const_iterator it = uid_sessions_.find(uid);

  if (it != uid_sessions_.end()) {
    LOG_DEBUG("UidSessionMap Get, uid=" << uid << " session_size=" << it->second.size());
    return it->second;
  }

  LOG_DEBUG("UidSessionMap Get, uid=" << uid << " not found.");
  static std::set<std::string> empty;
  return empty;
}

bool UidSessionMap::Contains(int64_t uid, const std::string & session) const {
  MapType::const_iterator it = uid_sessions_.find(uid);
  if (it == uid_sessions_.end()) {
    return false;
  }
  return it->second.find(session) != it->second.end();
}

static std::string ConcatIds(const std::set<std::string> & ids) {
  std::stringstream res;
  std::set<std::string>::const_iterator it = ids.begin();
  int i = 0;
  for(; it != ids.end(); ++it) {
    if (i++ > 0) {
      res << ',';
    }
    res << *it;
  }
  return res.str();
}

void UidSessionMap::Dump() const {
  if (uid_sessions_.size() > 1000) {
    return;
  }
  MapType::const_iterator it = uid_sessions_.begin();
  LOG_INFO("UidSessionMap dump BEGIN.");
  for(; it != uid_sessions_.end(); ++it) {
    LOG_INFO("UidSessionMap dump " << it->first << ' ' << ConcatIds(it->second));
  }
  LOG_INFO("UidSessionMap dump END.");
}

}

